/*
 * Description:  Common Utils in windows
 */

#ifndef GUESTUTILS_H
#define GUESTUTILS_H
#include <string>
#include <vector>
#include <windows.h>
#include <WtsApi32.h>

namespace COMMON {

#define SAFE_CLOSE_HANDLE(handle, defaultValue) \
if ((handle) != (defaultValue)) {           \
    CloseHandle(handle);                    \
    (handle) = (defaultValue);              \
}

class GuestUtils {
public:
    /********************
    函数：CalcHash
    功能：计算文件的sha256结果
    参数：文件路径
    返回值：hash结果
     ********************/
    static std::string CalcHash(std::string &filePath);

    /********************
    函数：IsDirEmpty
    功能：判断文件夹是否为空
    参数：文件路径
    返回值：是否为空文件夹
     ********************/
    static bool IsDirEmpty(std::string &filePath);

    /********************
    函数：IsFirstSet
    功能：是否为首次设置标志位
    参数：标志位
    返回值：是否为首次设置
     ********************/
    static bool IsFirstSet(const std::string &flag);

    /********************
    函数：ResetFirst
    功能：清理首次设置
    参数：标志位
    返回值：NA
     ********************/
    static void ResetFirst(const std::string &flag);

    /********************
    函数：ExecCmd
    功能：执行指定cmd, 是否需要用户身份
    参数：待执行的cmd
    返回值：是否执行成功
     ********************/
    static bool ExecCmd(const std::string &cmd, bool isUser, bool isTimeLimited = true);

    static int ExecCmdResult(const std::string &cmd, bool isUser);

    /********************
    函数：IsIpConnected
    功能：校验指定ip是否可访问
    参数：ip地址
    返回值：是否可访问
     ********************/
    static bool IsIpReachable(const std::string &ip);

    /********************
    函数：SetNetCard
    功能：指定网卡为静态ip地址,并指定网关
    参数：ip地址，网关地址
    返回值：是否设置成功
     ********************/
    static bool SetNetCard(const std::string &ip, const std::string &gateway, bool autoSyncHostDns = false);

    /********************
     * 函数：SetProxy
     * 功能：设置代理
     * 参数：代理使能，代理服务器，代理排除项
     * 返回：设置结果
     ********************/
    static bool SetProxy(const std::string& server, const std::string& exclusions);

    /********************
     * 函数：SetDNS
     * 功能：设置DNS
     * 参数：主DNS，备DNS
     * 返回：设置结果
     ********************/
    static bool SetDNS(const std::string& primaryDNS, const std::string& secondaryDNS);

    /********************
    * 函数：NetMap
    * 功能：执行net use映射
    * 参数：NA
    * 返回：NA
    ********************/
    static void NetMap(const std::string &gateway);

	/********************
	* 函数：SetVmTime
	* 功能：修改windows系统时间
	* 参数：主机的当前时间
	* 返回：是否修改成功
	********************/
    static bool SetVmTime(SYSTEMTIME &systemTime);

    /********************
	* 函数：SetVmTimeZone
	* 功能：修改windows系统时区
	* 参数：主机的时区差值
	* 返回：是否修改成功
	********************/
    static bool SetVmTimeZone(int timeZoneOffset);

    /********************
    * 函数：ExecCmd
    * 功能：执行指定cmd, 是否需要用户身份
    * 参数：cmd 待执行的cmd
    * 参数: isUser 是否需要用户身份
    * 参数: exitCode 执行返回代码
    * 返回值：是否执行成功
    *********************/
    static bool ExecCmdWithExitCode(const std::string &cmd, bool isUser, DWORD &exitCode, bool isTimeLimited = true);

    /********************
    函数：ExecCmdWithOutput
    功能：执行指定cmd, 是否需要用户身份
    * 参数：cmd 待执行的cmd
    * 参数: isUser 是否需要用户身份
    * 参数: output 子进程输出
    返回值：是否执行成功
     ********************/
    static bool ExecCmdWithOutput(const std::string &cmd, bool isUser, std::string &output);

    /********************
    * 函数：CreateUserProcess
    * 功能：创建用户进程
    * 返回值：创建是否成功
    *********************/
    static bool CreateUserProcess(const std::string &cmd, STARTUPINFO &si, PROCESS_INFORMATION &pi);

    /********************
    * 函数：GetLastAvailableLetter
    * 功能：从Z-A枚举获取可用的盘符
    * 返回值：可用盘符
    *********************/
    static std::string GetLastAvailableLetter();

    /********************
    * 函数：InitDisplay
    * 功能：首次启用2D时初始化
    * 参数：surfaceWidth，虚拟机surface宽度
    * 参数：surfaceHeight，虚拟机surface高度
    * 返回值: NA
    *********************/
    static void InitDisplay(uint32_t surfaceWidth, uint32_t surfaceHeight);

    /********************
    * 函数：ModifyResolution
    * 功能：修改分辨率
    * 参数：surfaceWidth，虚拟机surface宽度
    * 参数：surfaceHeight，虚拟机surface高度
    * 返回值: 修改是否成功
    *********************/
    static bool ModifyResolution(uint32_t surfaceWidth, uint32_t surfaceHeight, bool isInstall);

    /********************
    * 函数：GetTargetResolution
    * 功能：计算期望设置的分辨率
    * 参数：surfaceWidth，虚拟机surface宽度
    * 参数：surfaceHeight，虚拟机surface高度
    * 返回值: NA
    *********************/
    static std::pair<uint32_t, uint32_t> GetTargetResolution(uint32_t surfaceWidth, uint32_t surfaceHeight,
                                                             bool isInstall);

    static int GetAvailableLetterCount();

    /********************
     * 函数：ReadCurrentUserFlag
     * 功能：读当前用户注册表（注册表项为REG_DWORD类型）
     * 返回值: NA
     *********************/
    static DWORD ReadCurrentUserFlag(const std::string &root, const std::string &name);

    /********************
     * 函数：SetRegValueForCurrentUser
     * 功能：写当前用户注册表
     * 返回值: NA
     *********************/
    static bool SetRegValueForCurrentUser(
        const std::string &root, const std::string &name, const DWORD dwType, const std::string &value);

    /********************
     * 函数：GetServiceState
     * 功能：根据服务名称获取服务状态
     * 返回值: 服务状态
     *********************/
    static DWORD GetServiceState(const std::string &serviceName);

    /********************
     * 函数：GetCurrentUsername
     * 功能：获取当前用户用户名
     * 返回值: 取值结果
     *********************/
    static bool GetCurrentUsername(std::string& username);

    /********************
    * 函数：IsProcessRunning
    * 功能：根据进程名判断进程是否存在
    * 参数：进程名
    * 返回：进程是否存在
    ********************/
    static bool IsProcessRunning(const std::string& process_name);

     /********************
    * 函数：W32timeSet
    * 功能：设置w32time安全时间种子
    * 返回：设置是否成功
    ********************/
    static bool W32timeSet();

    /********************
    * 函数：SetHostDomainAccountAndSN
    * 功能：设置Host侧域账号和SN
    * 返回：设置是否成功
    ********************/
    static bool SetHostDomainAccountAndSN(const std::string& domainAccountName, const std::string& sn);

private:
    /********************
    * 函数：AquriePri
    * 功能：获取指定权限
    * 参数：所需权限名
    * 返回：是否获取成功
    ********************/
    static bool AquriePri(LPCTSTR privilegeName);

    /********************
    * 函数：DupUserToken
    * 功能：复制用户Token
    * 参数：NA
    * 返回：用户Token
    ********************/
    static bool DupUserToken(HANDLE &newToken);

    /********************
     * 函数：GetCurrentUserRegKey
     * 功能：获取当前用户的用户子项
     * 返回值: NA
     *********************/
    static std::string GetCurrentUserRegKey();

    static bool CreateProcessCustomized(const std::string &cmd, bool isUser, STARTUPINFO &si, PROCESS_INFORMATION &pi,
                                        HANDLE &hDupedToken);
    static bool GenStartupInfo(HANDLE &handleRead, HANDLE &handleWrite, STARTUPINFO &startupInfo);
    static void GetExecuteResult(const HANDLE handleRead, std::string &retStr);

    static bool GetCurrentUserNameBySessionId(std::string& username, DWORD sessionId);
};
}
#endif